/*
**    Copyright (C) 2003-2011 Institute for Systems Biology
**                            Seattle, Washington, USA.
**
**    This library is free software; you can redistribute it and/or
**    modify it under the terms of the GNU Lesser General Public
**    License as published by the Free Software Foundation; either
**    version 3 of the License, or (at your option) any later version.
**
**    This library is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**    Lesser General Public License for more details.
**
**    You should have received a copy of the GNU Lesser General Public
**    License along with this library; if not, write to the Free Software
**    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

package org.systemsbiology.iteration;

import java.util.Iterator;

/**
 * A base class made for anonymous overrides to quickly derive one iteration from another.
 * @author anorberg
 *
 * @param <In>   Type of the original iterator.
 * @param <Out>  Type to produce in the derived iterator.
 */
public abstract class IterableConverter<In, Out> implements Iterable<Out> {

	private Iterable<? extends In> source;
	
	/**
	 * Constructs an IterableConverter. IterableConverter is abstract, so
	 * convertValue must be overridden. This constructor is for use with
	 * the implicit superconstructor rule for parameters to anonymous classes
	 * (for spot single-method overrides).
	 * @param source  Iterable to pull an Iterator out of, the values of which
	 * 				  will be passed in order to convertValue() from within the
	 *                convert() method of the created anonymous IteratorConverter.
	 */
	public IterableConverter(Iterable<? extends In> source){
		assert(source != null);
		this.source = source;
	}

	public Iterator<Out> iterator() {
		return new IteratorConverter<In, Out>(source.iterator()){
			protected Out convert(In next) {
				return convertValue(next);
			}
			
		};
	}

	/**
	 * Method for converting the results of the source's iterator to the
	 * iterator we would like to provide. Be very careful when using any
	 * variables at class scope, since this method "lives in" the IterableConverter
	 * but will be called by the inner IteratorConverter class created;
	 * multiple concurrent or semi-concurrent iterations of one IterableConverter
	 * will result in arbitrary call order to this method.
	 * @param next  The result of a call to source.next().
	 * @return    The corresponding Out that should be provided from the translated iterator.
	 */
	protected abstract Out convertValue(In next);
	
	
}
